package org.kyrin.koala.aspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.kyrin.koala.annotation.ChangeTo;
import org.kyrin.koala.annotation.DataSourceDistribute;
import org.kyrin.koala.annotation.DataSourceEntity;
import org.kyrin.koala.annotation.DataSourceGroup;
import org.kyrin.koala.annotation.Group;
import org.kyrin.koala.datasource.DynamicDataSource;
import org.springframework.core.annotation.Order;
/**
* ***********************
*
* dataSourceAspect
*
* ***********************
* @author kyrin kyrincloud@qq.com
*
* @date [2015年5月4日]
*
*/
@Aspect
@Order(value=0)
public class DataSourceAspect {
private static Logger logger=Logger.getLogger(DataSourceAspect.class);
@Pointcut(value="@annotation(org.kyrin.koala.annotation.ChangeTo)")
public void inWebSevice(){}
@Pointcut(value="@within(org.kyrin.koala.annotation.DataSourceDistribute)")
public void inWebServiceClass(){}
@Pointcut(value="@within(org.kyrin.koala.annotation.DataSourceGroup)")
public void inWebServiceClass2(){}
@Pointcut(value="inWebServiceClass() || inWebServiceClass2()")
public void all(){}
//添加synchronized关键字,避免在同一个group下的数据源轮训不均匀
@Before(value="all()")
public synchronized void classBefore(JoinPoint jp){
MethodSignature sig=(MethodSignature) jp.getSignature();
Method method=sig.getMethod();
String name=method.getName();
Annotation annotation=method.getAnnotation(ChangeTo.class);
if(annotation!=null){
return;
}
Object obj=jp.getTarget();
DataSourceDistribute dataSourceDistribute=obj.getClass().getAnnotation(DataSourceDistribute.class);
DataSourceGroup dataSourceGroup=obj.getClass().getAnnotation(DataSourceGroup.class);
if(dataSourceDistribute!=null){
if(dealDataSourceDistribute(dataSourceDistribute,name)){
return;
}
}
if(dataSourceGroup!=null){
dealDataSourceGroup(dataSourceGroup,name);
}
}
private boolean dealDataSourceDistribute(DataSourceDistribute dataSourceDistribute,String methodName){
DataSourceEntity [] entity=dataSourceDistribute.value();
if(entity!=null){
for(DataSourceEntity en:entity){
if(Pattern.matches(en.methodPattern(), methodName)){
DynamicDataSource.changeTo(en.dataSource());
return true;
}
}
}
return false;
}
private boolean dealDataSourceGroup(DataSourceGroup dataSourceGroup,String methodName){
Group[] groups=dataSourceGroup.groups();
if(groups!=null){
for(Group group:groups){
if(Pattern.matches(group.methodPattern(), methodName)){
DynamicDataSource.getInstance().changeToByGroup(group.groupName());
return true;
}
}
}
return false;
}
@Around(value="inWebSevice()")
public void around(ProceedingJoinPoint pj) throws Throwable{
logger.info("The Around has been start !");
MethodSignature sig=(MethodSignature) pj.getSignature();
Method method=sig.getMethod();
Annotation annotation=method.getAnnotation(ChangeTo.class);
if(annotation!=null){
ChangeTo changeTo=(ChangeTo)annotation;
DynamicDataSource.changeTo(changeTo.value());
logger.info("Success change dataSource to :"+changeTo.value());
}
pj.proceed();
logger.info("The Around has been stop !");
}
}